"""
网站配置管理模块
提供系统配置项的读取、更新和管理功能
支持多类型配置项，包括文本、图片、开关等
"""

import json
import os
from datetime import datetime
from flask import current_app, request, jsonify, url_for
from werkzeug.utils import secure_filename
from app.core.extensions import db
from app.models.system import AdminLog

# 数据库表创建SQL (MySQL)
"""
CREATE TABLE IF NOT EXISTS `system_config` (
    `id` INT PRIMARY KEY AUTO_INCREMENT,
    `config_key` VARCHAR(64) NOT NULL UNIQUE COMMENT '配置键名',
    `config_value` TEXT COMMENT '配置值',
    `value_type` VARCHAR(20) COMMENT '值类型：string, number, boolean, json, image, file',
    `group_name` VARCHAR(50) COMMENT '分组：site, payment, email, social等',
    `description` VARCHAR(255) COMMENT '描述',
    `is_public` BOOLEAN DEFAULT FALSE COMMENT '是否对前端公开',
    `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表';

-- 初始数据
INSERT INTO `system_config` (`config_key`, `config_value`, `value_type`, `group_name`, `description`, `is_public`) VALUES
('site_name', '学法减分题库', 'string', 'site', '网站名称', 1),
('site_logo', '/static/images/logo.png', 'image', 'site', '网站Logo', 1),
('site_description', '专业的学法减分平台', 'string', 'site', '网站描述', 1),
('admin_email', 'admin@example.com', 'string', 'contact', '管理员邮箱', 0),
('show_banner', 'true', 'boolean', 'ui', '是否显示首页Banner', 1),
('registration_enabled', 'true', 'boolean', 'user', '是否允许新用户注册', 1),
('icp_number', '京ICP备XXXXXXXX号', 'string', 'legal', 'ICP备案号', 1),
('max_login_attempts', '5', 'number', 'security', '最大登录尝试次数', 0),
('service_tel', '400-123-4567', 'string', 'contact', '客服电话', 1),
('wechat_qrcode', '/static/images/wechat.jpg', 'image', 'social', '微信公众号二维码', 1);
"""


# 定义配置模型 (与Flask-SQLAlchemy集成)
class SystemConfig(db.Model):
    __tablename__ = 'system_config'
    id = db.Column(db.Integer, primary_key=True)
    config_key = db.Column(db.String(64), unique=True, nullable=False)
    config_value = db.Column(db.Text)
    value_type = db.Column(db.String(20))
    group_name = db.Column(db.String(50))
    description = db.Column(db.String(255))
    is_public = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=datetime.now)
    updated_at = db.Column(db.DateTime, onupdate=datetime.now)
    tenant_id = db.Column(db.Integer, db.ForeignKey('tenants.id'), nullable=True, comment='租户ID')

    def to_dict(self):
        """转换为字典，用于API返回"""
        return {
            'id': self.id,
            'key': self.config_key,
            'value': self._convert_value(),
            'type': self.value_type,
            'group': self.group_name,
            'description': self.description,
            'is_public': self.is_public,
            'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S') if self.updated_at else None
        }

    def _convert_value(self):
        """根据类型转换值"""
        if not self.config_value:
            return None

        if self.value_type == 'number':
            try:
                return float(self.config_value)
            except:
                return 0
        elif self.value_type == 'boolean':
            return self.config_value.lower() in ('true', '1', 'yes')
        elif self.value_type == 'json':
            try:
                return json.loads(self.config_value)
            except:
                return {}
        elif self.value_type in ('image', 'file'):
            # 返回完整URL
            if self.config_value.startswith(('http://', 'https://')):
                return self.config_value
            else:
                return self.config_value
        else:
            # 字符串或其他类型
            return self.config_value


def get_config(key, default=None):
    """
    获取单个配置项
    
    参数:
        key (str): 配置键名
        default: 默认值，如果配置不存在则返回此值
    
    返回:
        配置值，根据配置类型自动转换
    """
    # 直接从数据库查询
    config_item = SystemConfig.query.filter_by(config_key=key).first()

    if config_item:
        return config_item._convert_value()

    return default


def get_all_configs():
    """
    获取所有配置项
    
    返回:
        dict: 所有配置的字典，键为config_key，值为转换后的值
    """
    # 直接从数据库查询所有配置
    all_items = SystemConfig.query.all()
    return {item.config_key: item._convert_value() for item in all_items}


def get_public_configs():
    """
    获取所有公开的配置项，用于前端
    
    返回:
        dict: 公开配置的字典
    """
    # 直接从数据库查询所有公开配置
    public_items = SystemConfig.query.filter_by(is_public=True).all()
    return {item.config_key: item._convert_value() for item in public_items}


def set_config(key, value, value_type=None, group=None, description=None, is_public=None, admin_id=None):
    """
    设置配置项
    
    参数:
        key (str): 配置键名
        value: 配置值
        value_type (str, optional): 值类型
        group (str, optional): 分组
        description (str, optional): 描述
        is_public (bool, optional): 是否公开
        admin_id (int, optional): 管理员ID，用于记录日志
    
    返回:
        bool: 操作是否成功
    """
    # 查找现有配置项
    config_item = SystemConfig.query.filter_by(config_key=key).first()
    old_value = None
    if config_item:
        # 更新现有配置
        old_value = config_item.config_value
        config_item.config_value = str(value)

        if value_type is not None:
            config_item.value_type = value_type
        if group is not None:
            config_item.group_name = group
        if description is not None:
            config_item.description = description
        if is_public is not None:
            config_item.is_public = is_public
    else:
        # 创建新配置
        config_item = SystemConfig(
            config_key=key,
            config_value=str(value),
            value_type=value_type or 'string',
            group_name=group or 'other',
            description=description or '',
            is_public=is_public or False
        )
        db.session.add(config_item)

    # 记录管理日志
    if admin_id:
        log = AdminLog(
            admin_id=admin_id,
            action=f'修改配置: {key}',
            ip=request.remote_addr if request else '',
            details=f'将 {key} 从 "{old_value if config_item else "无"}" 修改为 "{value}"'
        )
        db.session.add(log)

    # 提交更改
    try:
        db.session.commit()
        return True
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"设置配置失败: {str(e)}")
        return False


def delete_config(key, admin_id=None):
    """
    删除配置项
    
    参数:
        key (str): 配置键名
        admin_id (int, optional): 管理员ID，用于记录日志
    
    返回:
        bool: 操作是否成功
    """
    config_item = SystemConfig.query.filter_by(config_key=key).first()
    if not config_item:
        return False

    # 记录管理日志
    if admin_id:
        log = AdminLog(
            admin_id=admin_id,
            action=f'删除配置: {key}',
            ip=request.remote_addr if request else '',
            details=f'删除配置项 {key}，原值为 "{config_item.config_value}"'
        )
        db.session.add(log)

    # 删除配置
    try:
        db.session.delete(config_item)
        db.session.commit()
        return True
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"删除配置失败: {str(e)}")
        return False


def upload_config_file(key, file, file_type='image', group='uploads', is_public=True, admin_id=None):
    """
    上传配置文件(图片等)
    
    参数:
        key (str): 配置键名
        file: 文件对象
        file_type (str): 文件类型，默认为'image'
        group (str): 分组
        is_public (bool): 是否公开
        admin_id (int, optional): 管理员ID
    
    返回:
        tuple: (成功标志, 消息或URL)
    """
    if not file:
        return False, '没有文件'

    filename = secure_filename(file.filename)
    # 确保文件名唯一
    unique_filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{filename}"

    # 确定保存路径
    upload_folder = current_app.config.get('UPLOAD_FOLDER', 'static/uploads')
    if not os.path.exists(upload_folder):
        os.makedirs(upload_folder)

    sub_folder = 'images' if file_type == 'image' else 'files'
    save_path = os.path.join(upload_folder, sub_folder)
    if not os.path.exists(save_path):
        os.makedirs(save_path)

    file_path = os.path.join(save_path, unique_filename)

    # 保存文件
    try:
        file.save(file_path)
        # 转换为相对路径，用于存储
        relative_path = f"/{file_path.replace(os.path.sep, '/')}"

        # 设置配置项
        if set_config(
                key,
                relative_path,
                value_type=file_type,
                group=group,
                description=f'{key} 文件',
                is_public=is_public,
                admin_id=admin_id
        ):
            return True, relative_path
        else:
            # 配置保存失败，删除文件
            os.remove(file_path)
            return False, '配置保存失败'
    except Exception as e:
        current_app.logger.error(f"文件上传失败: {str(e)}")
        return False, f'文件上传失败: {str(e)}'


# API 路由定义 (可以添加到Flask应用的蓝图中)
"""
以下是API路由示例，可以添加到您的Flask应用中:

# 前端获取公开配置
@app.route('/api/v1/configs/public', methods=['GET'])
def get_public_configs_api():
    return jsonify({
        'code': 0,
        'message': '获取成功',
        'data': get_public_configs()
    })

# 管理员获取所有配置
@app.route('/api/v1/admin/configs', methods=['GET'])
@jwt_required()
@admin_required
def get_all_configs_api():
    # 获取配置分组
    group = request.args.get('group')
    
    all_configs = SystemConfig.query.order_by(SystemConfig.group_name, SystemConfig.config_key)
    if group:
        all_configs = all_configs.filter_by(group_name=group)
    
    return jsonify({
        'code': 0,
        'message': '获取成功',
        'data': [core.to_dict() for core in all_configs.all()]
    })

# 管理员更新配置
@app.route('/api/v1/admin/configs/<key>', methods=['PUT'])
@jwt_required()
@admin_required
def update_config_api(key):
    data = request.json
    value = data.get('value')
    
    # 获取管理员ID
    admin_id = get_jwt_identity()
    
    success = set_config(
        key,
        value,
        value_type=data.get('type'),
        group=data.get('group'),
        description=data.get('description'),
        is_public=data.get('is_public'),
        admin_id=admin_id
    )
    
    if success:
        return jsonify({
            'code': 0,
            'message': '更新成功'
        })
    else:
        return jsonify({
            'code': 1,
            'message': '更新失败'
        }), 500

# 管理员上传配置文件
@app.route('/api/v1/admin/configs/upload/<key>', methods=['POST'])
@jwt_required()
@admin_required
def upload_config_file_api(key):
    if 'file' not in request.files:
        return jsonify({
            'code': 1,
            'message': '没有上传文件'
        }), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({
            'code': 1,
            'message': '没有选择文件'
        }), 400
    
    file_type = request.form.get('type', 'image')
    group = request.form.get('group', 'uploads')
    is_public = request.form.get('is_public', 'true').lower() in ('true', '1', 'yes')
    
    # 获取管理员ID
    admin_id = get_jwt_identity()
    
    success, result = upload_config_file(
        key, 
        file, 
        file_type=file_type,
        group=group,
        is_public=is_public,
        admin_id=admin_id
    )
    
    if success:
        return jsonify({
            'code': 0,
            'message': '上传成功',
            'data': {
                'url': result
            }
        })
    else:
        return jsonify({
            'code': 1,
            'message': result
        }), 500
"""
